package com.btl.component.crypto.aes;

import com.btl.boot.core.util.JsonUtils;
import com.btl.boot.exception.SysException;
import com.btl.component.crypto.aes.dto.ByteArrayHttpInputMessage;
import com.btl.component.crypto.aes.dto.CryptoDto;
import com.btl.component.crypto.aes.exception.DecryptException;
import com.btl.component.crypto.aes.util.AESCryptoUtil;
import com.btl.component.crypto.aes.util.RSACryptoUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;

@Slf4j
public class SecurityCrypt {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static ByteArrayHttpInputMessage decrypt(String encryptedData, HttpHeaders headers) {
        try {
            CryptoDto secReq = objectMapper.readValue(encryptedData, CryptoDto.class);
            boolean verify = RSACryptoUtil.verify(secReq.getKey() + secReq.getPayload(), secReq.getSignature());
            if (verify) {
                String aesKey = RSACryptoUtil.decrypt(secReq.getKey());
                String decryptPayload = AESCryptoUtil.decrypt(secReq.getPayload(), aesKey);
                return new ByteArrayHttpInputMessage(decryptPayload.getBytes(StandardCharsets.UTF_8), headers);
            } else {
                throw new SysException("签名异常");
            }
        } catch (SysException e) {
            throw new DecryptException(e.getMessage());
        } catch (Exception e) {
            throw new DecryptException("解密异常");
        }
    }

    public static Object encrypt(Object body) {
        CryptoDto secReq = new CryptoDto();
        try {
            String key = AESCryptoUtil.generateKey();
            String dataStr = JsonUtils.toJsonString(body);
            if (StringUtils.hasText(dataStr)) {
                String encryptData = AESCryptoUtil.encrypt(dataStr, key);
                String encryptKey = RSACryptoUtil.encrypt(key);
                String sign = RSACryptoUtil.sign(encryptKey + encryptData);
                secReq.setKey(encryptKey);
                secReq.setPayload(encryptData);
                secReq.setSignature(sign);
            }
        } catch (SysException e) {
            throw new DecryptException(e.getMessage(), e);
        } catch (Exception e) {
            log.error("加密异常", e);
            throw new DecryptException("加密异常");
        }
        return secReq;
    }


}
